![]() | |
|
|
|
To access the contents, click the chapter and section titles.
Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
The ErrorStack collection contains a series of RoutineInfo objects. When a routine encounters an error, it calls the AddToErrorStack routine to record information about itself. AddToErrorStack takes as parameters the name of the routine and the names and values of its variables. It creates a new RoutineInfo object and adds it to the ErrorStack collection. If the routines reraise parameter is True, AddToErrorStack raises the errStackDump error. That makes control pass one routine higher up the call stack. The ErrorStackText function in the StackInfo.bas module returns a textual representation of the stack trace. It then empties the stack so it will be ready for the next error.
Manage an error stack.
Option Explicit
Error code to represent a stack dump.
Public Const errStackDump = 41001
The collection of routine information.
Private ErrorStack As Collection
The error information that started it all.
Private ErrorNumber As Long
Private ErrorSource As String
Private ErrorDescription As String
Private ErrorHelpFile As String
Private ErrorHelpContext As Long
Create a RoutineInfo object, save the values
in it, and add it to the top of the ErrorStack
collection.
Public Sub AddToErrorStack(ByVal reraise As Boolean, _
ByVal routine_name As String, _
ParamArray variable_values() As Variant)
Dim routine_info As New RoutineInfo
Dim variable_num As Integer
Make sure we have an even number of
variable_values items because variable
names and values come in pairs.
If (UBound(variable_values) + 1) Mod 2 <> 0 Then Stop
If this is the first error in the stack,
allocate the stack and save error information.
If ErrorStack Is Nothing Then ClearErrorStack
Save the RoutineInfo values.
routine_info.SaveName routine_name
For variable_num = 0 To UBound(variable_values) Step 2
routine_info.SaveValue _
variable_values(variable_num), _
variable_values(variable_num + 1)
Next variable_num
Add the new RoutineInfo item to the top of
the ErrorStack stack.
If ErrorStack.Count = 0 Then
ErrorStack.Add routine_info
Else. ErrorStack.Add routine_info, , 1
End If
If we should reraise the error, do so.
If reraise Then _
Err.Raise ErrorNumber, ErrorSource, _
ErrorDescription, ErrorHelpFile, _
ErrorHelpContext
End Sub
Allocate the stack and save the current error
information.
Public Sub ClearErrorStack()
Start with a new stack collection.
Set ErrorStack = New Collection
Save the error values.
ErrorNumber = Err.Number
ErrorSource = Err.Source
ErrorDescription = Err.Description
ErrorHelpFile = Err.HelpFile
ErrorHelpContext = Err.HelpContext
End Sub
Return a textual representation of the stack.
Public Function ErrorStackText() As String
Dim routine_info As RoutineInfo
Dim result As String
Dim num_spaces As Integer
Make sure there is stack info.
If ErrorStack Is Nothing Then Stop
Start with the error information.
result = Error & Format$(ErrorNumber) & _
. & vbCrLf & Err.Description & vbCrLf & _
vbCrLf & Stack dump: & vbCrLf
Create the entries for each routine.
For Each routine_info In ErrorStack
Add this routines information.
result = result & routine_info.TextValue(num_spaces).
num_spaces = num_spaces + 4
Next routine_info
ErrorStackText = result
Empty the stack.
Set ErrorStack = Nothing
End Function
All this elaborate preparation allows the actual error handlers in the main program to be relatively simple. If a routine that is called by another encounters an error, it simply calls AddToErrorStack to save its trace information. It sets the reraise parameter to True so AddToErrorStack raises the errStackDump error when it finishes. Control moves up the call stack until Visual Basic finds an installed error handler. Because the routine that called AddToErrorStack is already executing in an error handler, control moves past that routine to the routine that called it. For example, in Figure 13.2, subroutine Sub_A calls subroutine Sub_A_1. When Sub_A_1 encounters an error, it calls AddToErrorStack. That routine raises the errStackDump error and control moves back up the stack. Because Sub_A_1 is already executing an error handler, control passes up the stack to Sub_A. Then Sub_A also invokes AddToErrorStack. That records information about Sub_A and reraises the errStackDump error. Control continues up the call stack. The following code shows how subroutine Sub_A_1 handles errors. If its option button is selected, it raises an error itself. If the button is not selected, it invokes subroutine Sub_A_1_1. In any case, if the routine encounters an error, it calls AddToErrorStack.
Private Sub Sub_A_1()
Dim txt As String
On Error GoTo Sub_A_1_Error
txt = In Sub_A_1
If optError(errSub_A_1).Value Then Err.Raise 9
Sub_A_1_1
Exit Sub
Sub_A_1_Error:
Save our information and start or continue
a stack dump.
AddToErrorStack True, Sub_A_1, txt, txt
End Sub
Eventually, control moves all the way up the call stack until it reaches the routine that started the code running; usually, that is an event handler. In program StackDmp, the event handler that starts it all is cmdExecute_Click. When this routine encounters an error, it calls subroutine AddToErrorStack much as the other routines do. This time, however, it sets the reraise parameter to False so AddToErrorStack does not raise the errStackDump error. If it raised an error, control would pass beyond the programs code and the application would crash. After calling AddToErrorStack, the event handler uses the ErrorStackText function to build and display the final stack trace message. In this case, the program displays the message in a TextBox. It could just as easily display it in a message box, save it to a file, write it to a database, or mail it to you and other developers as described in the following sections.
Clear txtResults and execute Sub_A. If there is
an error, display the results in txtResults.
Private Sub cmdExecute_Click()
Dim txt As String
On Error GoTo ExecuteError
txtResults.Text =
txt = In cmdExecute
If optError(errCmdExecute).Value Then Err.Raise 9
Sub_A
txtResults.Text = Ok
Exit Sub
ExecuteError:
Save our information but do not reraise
the stack dump error.
AddToErrorStack False, cmdExecute, txt, txt
Display the stack dump. This resets the stack.
txtResults.Text = ErrorStackText
Exit Sub
End Sub
This system is a bit tricky, so you may want to step through program StackDmp a few times in the debugger to see how things work. All of the code is available at the Web site. The complicated code is contained in the Stackerr.bas module and the RoutineInfo class. The main programs error handling code is fairly straightforward.
|
|
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.
|